//采用类的方式进行封装,会使代码更具复用性
class wxrequest {
  //定义实例属性
  default = {
    baseURL: '', //请求地址
    url: '', //接口请求路径
    data: null, //请求参数
    method: 'GET', //默认请求方法
    //设置请求头
    header: {
      'Content-type': 'application/json' //设置数据交互格式
    },
    timeout: 60000, //默认超时时间 一分钟,
    isLoading: true //表示是否使用loading 默认值true
  }

  //响应拦截器
  //包含请求拦截器和响应拦截器,方便请求及响应方便逻辑处理

  interceptors = {
    //请求拦截器
    //在请求发送之前,对请求参数进行新增或修改
    request: (config) => config,

    //响应拦截器
    //处理服务器响应数据
    response: (response) => response
  }

  //定义数组队列
  //初始值需要是一个空数组 ,用来存储请求标识
  queue = []

  //用于创建和初始化类的属性和方法
  //在实例化时传入参数会被constructor 形参接收
  constructor(params = {}) {
    // console.log(params)
    //通过 Object.assign合并请求参数
    //注意:传入参数,覆盖默认参数,传入参数在最后
    this.default = Object.assign({}, this.default, params)
  }

  //request实例方法接收一个对象类型的参数
  //属性值和wx.request参数要求一致
  request(options) {
    //判断是否存在定时器
    this.timeId && clearTimeout(this.timeId)
    //注意 需要先合并完整请求地址(baseURL+url)
    //https://gmall-prod.atguigu.cn/mall-api/
    options.url = this.default.baseURL + options.url
    //合并请求参数
    options = { ...this.default, ...options }

    //请求发送之前,添加loading效果
    // wx.showLoading({
    //   title: 'title'
    // })
    //判断queue是否为空 如果是空,则显示loading
    //如果不是空.就不显示loading ,不调用wx.showLoading
    if (options.isLoading && options.method !== 'UPLOAD') {
      this.queue.length === 0 && wx.showLoading()

      //然后向queue添加请求标识
      this.queue.push('request')
    }

    //在请求发送之前,调用请求拦截器,新增和修改参数
    options = this.interceptors.request(options)
    //使用promise 封装wx.request 处理异步请求
    return new Promise((resolve, reject) => {
      if (options.method === 'UPLOAD') {
        wx.uploadFile({
          ...options,
          success: (res) => {
            //需要将服务器返回JSON"转回对象
            res.data = JSON.parse(res.data)

            //合并参数
            const mergeRes = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })

            resolve(this.interceptors.response(mergeRes))
          },
          fail: (err) => {
            const mergeErr = Object.assign({}, res, {
              config: options,
              isSuccess: false
            })

            resolve(this.interceptors.response(mergeRes))
          }
        })
      } else {
        wx.request({
          ...options,

          //当接口成功调用时会触发
          success: (res) => {
            //不管成功与否,都需要调用响应拦截器
            //响应拦截器需要接收服务器的数据  对数据进行逻辑处理 处理好了进行返回
            //然后在 通过resolve 将返回数据抛出去

            //在响应拦截器传递参数时 需要将请求参数也一起传递
            //方便进行代码调试或者进行其他逻辑处理 ,需要合并参数
            //如何将返回参数传递给响应拦截器

            //不管请求失败还是成功 都已经将响应的数据传递给了响应拦截器
            //这时候合并参数的审核 追加了一个isSuccess
            //拦截器函数内部属性证明请求是否发送成功
            const mereRes = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })
            resolve(this.interceptors.response(mereRes))
          },
          //当接口失败时调用时会触发
          fail: (error) => {
            const mereError = Object.assign({}, error, {
              config: options,
              isSuccess: false
            })
            reject(this.interceptors.response(mereError))
          },

          //接口调用结束的回调函数(调用成功,失败都会执行)
          complete: () => {
            if (options.isLoading) {
              //请求结束后 删除队列标识
              this.queue.pop()
              //判断数组为空

              this.queue.length === 0 && this.queue.push('request')

              this.timeId = setTimeout(() => {
                this.queue.pop()
                //如果空,证明请求发送完成
                //需要隐藏loading ,调用wx.hideloading()
                this.queue.length === 0 && wx.hideLoading()
                clearTimeout(this.timeId)
              }, 1)
            }
          }
          //不管成功还是失败都需要隐藏loading
        })
      }
    })
  }

  //封装GET方法实例
  get(url, data = {}, config = {}) {
    //需要调用request方法发送请求,只需要做好参数传递给request
    //当调用get方法时,需要request方法返回值return出去
    return this.request(Object.assign({ url, data, method: 'get' }, config))
  }

  //封装DELETE方法实例
  delete(url, data = {}, config = {}) {
    return this.request(Object.assign({ url, data, method: 'DELETE' }, config))
  }

  //封装POST方法实例
  post(url, data = {}, config = {}) {
    return this.request(Object.assign({ url, data, method: 'POST' }, config))
  }

  //封装PUT方法实例
  put(url, data = {}, config = {}) {
    return this.request(Object.assign({ url, data, method: 'PUT' }, config))
  }

  //封装请求实例方法  all方法用来处理并发请求
  all(...promise) {
    // console.log(promise)
    //通过展开运算符接收传递参数
    //那么展开运算符传入的参数转化成数组
    // const res = Promise.all(promise)
    return Promise.all(promise)
  }
  //wx.upload封装
  upload(url, filePath, name = 'file', config = {}) {
    return this.request(
      Object.assign({ url, filePath, name, method: 'UPLOAD' }, config)
    )
  }
}

export default wxrequest
